/*! \file logger.c
    \brief Programa log. Se encarga de documentar toda la actividad que realiza el cliente
    
    Detalles.
*/
#include "error_parsing.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#define TAM 128
#define BUFFSIZE 256


/*! \fn void Dar_Formato(char input[TAM], int largo, int cant)
    \brief Da formato a las cadenas que van a escribirse del archivo
    \param input[TAM] Contiene la cadena que va a escribirse
    \param largo Especifica el largo de la cadena
    \param cant Cantidad de espacios que debe agregarse a la cadena
*/
void Dar_Formato(char input[TAM], int largo, int cant);

/*! \fn int Crear_Server_UNIX()
    \brief Crea un socket servidor de la familia UNIX.
    \return El \a file \a descriptor del socket cliente conectado \a newsockfd .
*/
int Crear_Server_UNIX();

/*!	\fn void Calcular_Tiempo(char output[TAM])
	\brief Determina la fecha y la hora en que se ejecuto el comando a documentar
	\param output[TAM] Almacena la fecha y la hora luego de ejecutar la funcion \a strftime(...)
 */
void Calcular_Tiempo(char output[TAM]);

/*!	\fn void Escribir_Archivo(FILE *f, char *buffer, int espacios)
	\brief Realiza una llamada a la funcion \a Dar_Formato y escribe en el 
			archivo el contenido de \a buffer
	\param *f Puntero a archivo que se desea escribir
	\param *buffer Contendra la cadena a escribir en el archivo
	\param espacios Cantidad de espacios que se debe agregar a la cadena que se va a 
		escribir en el archivo
 */
void Escribir_Archivo(FILE *f, char *buffer, int espacios);

/**
 * En la funcion \a main se realiza la comunicacion con el socket cliente
 * y la llamada a las demas funciones que involucran la escritura del archivo
 * \a comunicacion.log
 * */
int main (int argc, char* argv[])
{
	/*------------------------------------------------------------------
	 * 				Se crea un socket server UNIX
	 *----------------------------------------------------------------*/
	int desc_serv_UN;
	desc_serv_UN = Crear_Server_UNIX();
	
	/*------------------------------------------------------------------
	 * 			Se abre archivo para guardar registros
	 *----------------------------------------------------------------*/
	FILE *fich;
	
	fich = fopen("comunicacion.log", "wb");	
	if(!fich)
	{
		error("Abrir el archivo");
	}	
	
	/*Se ubica el indicador de posicion al inicio del fichero*/
	fseek(fich,0L,SEEK_SET);
	
	/*------------------------------------------------------------------
	 * 				Comunicacion con proceso Cliente
	 *----------------------------------------------------------------*/
	int terminar = 0; 		// Bandera que indica si hay que terminar la ejecucion
	char buffer[BUFFSIZE], resultado[BUFFSIZE];
	
	while(terminar == 0) 
	{ 
		bzero( buffer, BUFFSIZE );
		bzero( resultado, BUFFSIZE );
		
		/*--------------------------------------------------------------
		 * 					Se recibe el comando
		 *------------------------------------------------------------*/
		if(read( desc_serv_UN, buffer, BUFFSIZE ) < 0)
		{
			error( "Lectura de socket" );
		}
	
		/* Verificacion de si hay que terminar */
		if(strcmp( buffer,"bye")==0)
			terminar = 1;
	
		/*	 Escritura de comando en archivo   */
		Escribir_Archivo(fich, buffer,45);
		
		if(write( desc_serv_UN, "UNIX : Obtuve su mensaje", 24 ) < 0)
		{
			error( "Escritura en socket" );
		}

		/*--------------------------------------------------------------
		 * 		Se recibe el resultado de la ejecucion del comando
		 *------------------------------------------------------------*/
		if(read( desc_serv_UN, resultado, BUFFSIZE ) < 0)
		{
			error( "Lectura de socket" );
		}
		
		/*	 Escritura de resultado en archivo   */
		Escribir_Archivo(fich,resultado,45);

		/*--------------------------------------------------------------
		 * 			Determinar hora y fecha de ejecucion 
		 * 		   del comando y escribirlo en el archivo
		 *------------------------------------------------------------*/
		char output[TAM];			// Arreglo que almacena la fecha y hora
		Calcular_Tiempo(output);
		Escribir_Archivo(fich, output, 0);	

		if(write( desc_serv_UN, "UNIX : Obtuve su mensaje", 24 ) < 0)
		{
			error( "Escritura en socket" );
		}	
	}

	fclose(fich);
	close(desc_serv_UN);
    return 0;	
}

int Crear_Server_UNIX()
{
	struct sockaddr_un  cli_addr, serv_addr;
	int sockfd, servlen, newsockfd;
	socklen_t clilen;
	
	/* 		Se crea el socket   	*/
	if ( ( sockfd = socket( AF_UNIX, SOCK_STREAM, 0) ) < 0 ) 
	{
		error( "creación de  socket");
	}

    /* Remover el nombre de archivo si existe */
    unlink ( "logger_sys" );

	/*   Limpieza de la estructura 	*/
	memset( &serv_addr, 0, sizeof(serv_addr) );
	
	serv_addr.sun_family = AF_UNIX;
	strcpy( serv_addr.sun_path, "logger_sys" );
	servlen = strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family);

	/* Liga una direccion al socket */
	if( bind( sockfd,(struct sockaddr *)&serv_addr,servlen ) < 0 ) 
	{
		error( "bind" ); 
	}
	/*	Espera solicitud de conexion de clientes  */
	listen( sockfd, 1 );
	
	/* Acepta la solicitud de conexion de un cliente*/
	clilen = sizeof(cli_addr);
	newsockfd = accept( sockfd, (struct sockaddr *) &cli_addr, &clilen );
    if ( newsockfd < 0 ) 
    {
           error( "accept" );
    }	
	return newsockfd;
}

void Dar_Formato(char input[TAM], int largo, int cant)
{
	int i=0;
	for(i=largo;i<cant;i++)
		input[i]=' ';
}

void Escribir_Archivo(FILE *f, char *buffer, int espacios)
{
	Dar_Formato(buffer, strlen(buffer),espacios);
	fwrite(buffer,1,strlen(buffer),f);
}

void Calcular_Tiempo(char output[TAM])
{
	time_t tiempo = time(0);
	struct tm *tlocal = localtime(&tiempo);
		
	strftime(output,TAM,"%d/%m/%y %H:%M:%S\n",tlocal);	
}
